
class ManWaManHua extends ComicSource {
    // 注意: 标记为[可选]的字段如果不使用应删除

    // 源名称
    name = "漫蛙漫画"

    // 源的唯一标识
    key = "ManWaManHua"

    version = "1.0.1"

    minAppVersion = "1.4.0"

    // 更新链接
    url = "https://gitee.com/cmj_xxgg/comic_yuan/blob/master/漫蛙漫画.js"

    /**
     * [可选] 初始化函数
     */
    init() {
        this.baseUrl = "https://www.manwamh.com";
    }


    // 探索页面列表
    explore = [
        {
            // 页面标题
            // 标题用于标识页面，应保持唯一
            title: "漫蛙漫画",

            /// multiPartPage（多分区页面）或multiPageComicList（多页漫画列表）或mixed（混合类型）
            type: "singlePageWithMultiPart",

            // 分区列表
            load: async (page) => {

                // 1.获取网页内容
                let res = await Network.get(this.baseUrl);

                if (res.status !== 200) {
                    throw `Invalid status code: ${res.status}`
                }

                // 2. 解析文档
                let doc = new HtmlDocument(res.body);

                // 3. 通用解析单元函数
                function parseItem(el) {
                    // 获取id /comic/8608.html
                    let id = el.querySelector("a").attributes.href.replace('/comic/', '');
                    // 获取封面
                    let imgEl = el.querySelector("div.cover");
                    let cover = imgEl.attributes['data-original'];
                    // 获取标题
                    let title = el.querySelector("h3").text.trim();
                    return new Comic({ id, title, cover });
                }

                // 4. 获取热门漫画
                let hot = [];
                let hotList = doc.querySelectorAll("div.pure-g")[0];
                if (hotList) {
                    let items = hotList.querySelectorAll("div.comics-card");
                    for (let el of items) {
                        hot.push(parseItem(el));
                    }
                }

                // 5. 推荐国漫
                let guonei = [];
                let guoneiList = doc.querySelectorAll("div.pure-g")[1];
                if (guoneiList) {
                    let items = guoneiList.querySelectorAll("div.comics-card");
                    for (let el of items) {
                        guonei.push(parseItem(el));
                    }
                }

                // 6. 推荐日漫
                let riben = [];
                let ribenList = doc.querySelectorAll("div.pure-g")[2];
                if (ribenList){
                    let items = ribenList.querySelectorAll("div.comics-card");
                    for (let el of items) {
                        riben.push(parseItem(el));
                    }
                }

                // 7. 推荐韩漫
                let hanguo = [];
                let hanguoList = doc.querySelectorAll("div.pure-g")[2];
                if (hanguoList){
                    let items = hanguoList.querySelectorAll("div.comics-card");
                    for (let el of items) {
                        hanguo.push(parseItem(el));
                    }
                }

                // 8. 最近更新
                let recent = [];
                let recentList = doc.querySelectorAll("div.pure-g")[3];
                if (recentList){
                    let items = recentList.querySelectorAll("div.comics-card");
                    for (let el of items) {
                        recent.push(parseItem(el));
                    }
                }

                // 7. 清理并返回
                doc.dispose();
                return {
                    "热门漫画": hot,
                    "推荐国漫": guonei,
                    "推荐日漫": riben,
                    "推荐韩漫": hanguo,
                    "最近更新": recent
                };
            },
        }
    ]

    // 分类
    category = {
        /// 分类页面标题，用于标识页面，应保持唯一
        title: "ManWaMH",
        parts: [
            {
                // 分区标题
                name: "分类",

                // fixed（固定）或random（随机）或dynamic（动态）
                // 如果是random类型，需要提供`randomNumber`字段，表示同时显示的漫画数量
                // 如果是dynamic类型，需要提供`loader`字段，表示加载漫画的函数
                type: "fixed",

                categories: ["全部", "热血", "玄幻", "都市", "言情", "校园", "恋爱", "穿越", "搞笑", "竞技", "治愈", "大女主", "格斗", "体育", "冒险", "励志", "纯情", "奇幻", "系统", "古风", "灵异", "剧情", "动作", "科幻", "推理", "美少女", "其他"],

                itemType: "category",

                // 若提供, 数量需要和`categories`一致, `categoryComics.load`方法将会收到此参数
                categoryParams: ["", "rexue", "xuanhuan", "dushi", "yanqing", "xiaoyuan", "lianai", "chuanyue", "gaoxiao", "jingji", "zhiyu", "danvzhu", "gedou", "tiyu", "maoxian", "lizhi", "chunqing", "qihuan", "xitong", "gufeng", "lingyi", "juqing", "dongzuo", "kehuan", "tuili", "meishaonv", "qita"]
             }
        ],
        // 启用排行榜页面
        enableRankingPage: false,
    }

    /// 分类漫画加载相关
    categoryComics = {
        /**
         * 加载分类漫画
         * @param category {string} - category name
         * @param param {string?} - category param
         * @param options {string[]} - options from optionList
         * @param page {number} - page number
         * @returns {Promise<{comics: Comic[], maxPage: number}>}
         */
        load: async (category, param, options, page) => {

            // 分类网址
            // https://www.manwamh.com/category/theme/rexue
            // https://www.manwamh.com/category/theme/rexue?page=2&limit=36&theme=rexue

            let url = `${this.baseUrl}/category/theme/${param}&page=${page}&limit=36&theme=${param}`;
            // 发起请求
            let res = await Network.get(url);
            if (res.status !== 200) {
                throw `Invalid status code: ${res.status}`;
            }
            // 解析 HTML
            let document = new HtmlDocument(res.body);

            let maxPage = 99;

            // 获取漫画列表
            let mangaList = [];
            let rows = document.querySelectorAll(".comics-card");
            for (let row of rows) {
                    // 获取id /comic/8608.html
                    let id = row.querySelector("a").attributes.href.replace('/comic/', '');
                    // 获取封面
                    let imgEl = row.querySelector("div.cover");
                    let cover = imgEl.attributes['data-original'];
                    // 获取标题
                    let title = row.querySelector("h3").text.trim();
                    // 获取分类
                    let categorys = [];

                    //最近
                    let desc = row.querySelector("small").text.trim();
                    // 构建漫画对象
                    let manga = {
                        id: id,
                        title: title,
                        cover: cover, // 默认封面
                        tags: categorys,
                        description: desc
                    };

                    mangaList.push(manga);
            }

            return {
                comics: mangaList,
                maxPage: maxPage
            };
        },
        // // 为分类漫画加载提供选项
        // optionList: [
        //     {
        //         // 单个选项使用`-`分隔值和文本，左侧为值，右侧为文本
        //         options: [
        //             "newToOld-New to Old",
        //             "oldToNew-Old to New"
        //         ],
        //         // [可选] {string[]} - 仅当值不在列表中时显示此选项
        //         notShowWhen: null,
        //         // [可选] {string[]} - 仅当值在列表中时显示此选项
        //         showWhen: null
        //     }
        // ],
        // ranking: { // 排行榜
        //     // For a single option, use `-` to separate the value and text, left for value, right for text
        //     options: [
        //         "day-Day",
        //         "week-Week"
        //     ],
        //     /**
        //      * 加载排行榜漫画
        //      * @param option {string} - option from optionList
        //      * @param page {number} - page number
        //      * @returns {Promise<{comics: Comic[], maxPage: number}>}
        //      */
        //     load: async (option, page) => {
        //         /*
        //         ```
        //         let data = JSON.parse((await Network.get('...')).body)
        //         let maxPage = data.maxPage

        //         function parseComic(comic) {
        //             // ...

        //             return new Comic({
        //                 id: id,
        //                 title: title,
        //                 subTitle: author,
        //                 cover: cover,
        //                 tags: tags,
        //                 description: description
        //             })
        //         }

        //         return {
        //             comics: data.list.map(parseComic),
        //             maxPage: maxPage
        //         }
        //         ```
        //         */
        //     }
        // }
    }

    /// 搜索相关
    search = {
        /**
         * 加载搜索结果
         * @param keyword {string}
         * @param options {string[]} - options from optionList
         * @param page {number}
         * @returns {Promise<{comics: Comic[], maxPage: number}>}
         */
        load: async (keyword, options, page) => {
            // 搜索网址 https://www.manwamh.com/search?q=%E8%B6%85%E7%BA%A7
            let url = `${this.baseUrl}/search?q=${keyword}&page=${page}`;

            let res = await Network.get(url);

            if (res.status !== 200) {throw `Invalid status code: ${res.status}`;}

            let document = new HtmlDocument(res.body);
    
            // 获取最大页数
            // 首先找到aria-label="下一頁"的a标签
            let maxPage = 99;

              // 获取漫画列表
            let mangaList = [];
            let rows = document.querySelectorAll(".comics-card");
            for (let row of rows) {
                    // 获取id /comic/8608.html
                    let id = row.querySelector("a").attributes.href.replace('/comic/', '');
                    // 获取封面
                    let imgEl = row.querySelector("div.cover");
                    let cover = imgEl.attributes['data-original'];
                    // 获取标题
                    let title = row.querySelector("h3").text.trim();
                    // 获取分类
                    let categorys = [];

                    //最近
                    let desc = row.querySelector("small").text.trim();
                    // 构建漫画对象
                    let manga = {
                        id: id,
                        title: title,
                        cover: cover, // 默认封面
                        tags: categorys,
                        description: desc
                    };

                    mangaList.push(manga);
            }

            return {
                comics: mangaList,
                maxPage: maxPage
            };
        },

        /**
         * 使用下一页令牌加载搜索结果。
         * The field will be ignored if `load` function is implemented.
         * @param keyword {string}
         * @param options {(string)[]} - options from optionList
         * @param next {string | null}
         * @returns {Promise<{comics: Comic[], maxPage: number}>}
         */
        loadNext: async (keyword, options, next) => {
        },

        // 为搜索提供选项
        optionList: [
        ],

        // 启用标签建议
        enableTagsSuggestions: false,
    }

    // 收藏相关
    favorites = {
        // 是否支持多文件夹
        multiFolder: false,
        /**
         * 添加或删除收藏。
         * 抛出`Login expired`表示登录过期，应用将自动重新登录并重新添加/删除收藏
         * @param comicId {string}
         * @param folderId {string}
         * @param isAdding {boolean} - true for add, false for delete
         * @param favoriteId {string?} - [Comic.favoriteId]
         * @returns {Promise<any>} - return any value to indicate success
         */
        addOrDelFavorite: async (comicId, folderId, isAdding, favoriteId) => {
            /*
            ```
            let res = await Network.post('...')
            if (res.status === 401) {
                throw `Login expired`;
            }
            return 'ok'
            ```
            */
        },
        /**
         * 加载收藏文件夹。
         * throw `Login expired` to indicate login expired, App will automatically re-login retry.
         * if comicId is not null, return favorite folders which contains the comic.
         * @param comicId {string?}
         * @returns {Promise<{folders: {[p: string]: string}, favorited: string[]}>} - `folders` is a map of folder id to folder name, `favorited` is a list of folder id which contains the comic
         */
        loadFolders: async (comicId) => {
            /*
            ```
            let data = JSON.parse((await Network.get('...')).body)

            let folders = {}

            data.folders.forEach((f) => {
                folders[f.id] = f.name
            })

            return {
                folders: folders,
                favorited: data.favorited
            }
            ```
            */
        },
        /**
         * 添加文件夹
         * @param name {string}
         * @returns {Promise<any>} - return any value to indicate success
         */
        addFolder: async (name) => {
            /*
            ```
            let res = await Network.post('...')
            if (res.status === 401) {
                throw `Login expired`;
            }
            return 'ok'
            ```
            */
        },
        /**
         * 删除文件夹
         * @param folderId {string}
         * @returns {Promise<void>} - return any value to indicate success
         */
        deleteFolder: async (folderId) => {
            /*
            ```
            let res = await Network.delete('...')
            if (res.status === 401) {
                throw `Login expired`;
            }
            return 'ok'
            ```
            */
        },
        /**
         * 加载文件夹中的漫画
         * throw `Login expired` to indicate login expired, App will automatically re-login retry.
         * @param page {number}
         * @param folder {string?} - folder id, null for non-multi-folder
         * @returns {Promise<{comics: Comic[], maxPage: number}>}
         */
        loadComics: async (page, folder) => {
            /*
            ```
            let data = JSON.parse((await Network.get('...')).body)
            let maxPage = data.maxPage

            function parseComic(comic) {
                // ...

                return new Comic{
                    id: id,
                    title: title,
                    subTitle: author,
                    cover: cover,
                    tags: tags,
                    description: description
                }
            }

            return {
                comics: data.list.map(parseComic),
                maxPage: maxPage
            }
            ```
            */
        },
        /**
         * 使用下一页令牌加载漫画
         * @param next {string | null} - next page token, null for first page
         * @param folder {string}
         * @returns {Promise<{comics: Comic[], next: string?}>}
         */
        loadNext: async (next, folder) => {

        },
        /**
         * 如果漫画源只允许一个漫画在一个文件夹中，设置为true。
         */
        singleFolderForSingleComic: false,
    }

    /// 单部漫画相关
    comic = {
        /**
         * 加载漫画信息
         * @param id {string}
         * @returns {Promise<ComicDetails>}
         */
        loadInfo: async (id) => {
            // 详情网页 https://www.manwamh.com/comic/Eo1OYWey6B
            let url = `${this.baseUrl}/comic/${id}`;
            let res = await Network.get(url);
            if (res.status !== 200) {throw `Invalid status code: ${res.status}`;}
            let document = new HtmlDocument(res.body);

            let info = document.querySelector(".pure-g");

            // 漫画标题
            let title = info.querySelector("h1").text.trim();

            // 漫画封面
            let cover = info.querySelector("img");
            if(cover){
                cover = cover.attributes['src'];
            }

            // 漫画描述
            let description = info.querySelector("p.comics-detail__desc").text.trim();

            // 漫画作者
            let author = info.querySelector(".comics-detail__author").text.trim().replace("作者：", "");

            // 漫画标签
            let tags = [];
            info.querySelectorAll("div.tag-list > span").forEach(tag => {
                tags.push(tag.text.trim());
            });

            // 更新时间
            let updateStr = info.querySelector("em").text.trim();
            const timeMatch = updateStr.match(/(\d{4}-\d{2}-\d{2} \d{2}:\d{2})/);
            const updateTime = timeMatch ? timeMatch[0] : null;

            // 漫画章节
            let chapterRes = document.querySelectorAll("div.l-box")[1];
            let chapter_it = chapterRes.querySelectorAll("div#chapter-items > div");

            let chapterList;
            if (chapter_it.length > 0) {
                chapterList = chapter_it;
            }else{
                chapterList = chapterRes.querySelectorAll("div.pure-g > div");
            }

            let chapters = new Map();
            // 遍历 chapters 数组
            if (chapterList) {

                for (const chapter of chapterList) {
                    const chapterId = chapter.querySelector("a").attributes["href"];
                    const title = chapter.text.trim();
                    
                    // 如果 chapterId 和 title 都不为空，则添加到 Map 中
                    if (chapterId && title) {
                        chapters.set(chapterId, title);
                    }
                }
            }


            return {
                title: title,
                cover: cover,
                description: description,
                tags: {
                    "作者": [author],
                    "更新": [updateTime],
                    "标签": tags
                },
                chapters: chapters
            };
        },
        /**
         * 加载章节图片
         * @param comicId {string}
         * @param epId {string?}
         * @returns {Promise<{images: string[]}>}
         */
loadEp: async (comicId, epId) => {
        // 1. 请求 HTML
        const url = `${this.baseUrl}${epId}`;
            let res = await Network.get(url);
            if (res.status !== 200) {throw `Invalid status code: ${res.status}`;}
            let document = new HtmlDocument(res.body);

        // 2. 提取加密数据
        let encryptedData = null;
        const scripts = document.querySelectorAll('script');
        for (const script of scripts) {
            const match = script.innerHTML.match(/var\s+params\s*=\s*['"]([^'"]+)['"]/);
            if (match) {
                encryptedData = match[1];
                break;
            }
        }
        if (!encryptedData) throw new Error("未找到加密数据");

        // 3. 分离 IV 和 ciphertext
        let encryptedBuffer = Convert.decodeBase64(encryptedData);
        const ivBuffer = encryptedBuffer.slice(0, 16);
        const ciphertextBuffer = encryptedBuffer.slice(16);

        // 你的 hex 字符串
        const hexStr = "355626526f52254a6640704a50796446";

        // 先创建对应长度的 Uint8Array
        const bytes = new Uint8Array(hexStr.length / 2);

        // 遍历每两个字符，解析为一个字节
        for (let i = 0; i < hexStr.length; i += 2) {
            bytes[i / 2] = parseInt(hexStr.substr(i, 2), 16);
        }

        // 转为 ArrayBuffer
        const keyBuffer = bytes.buffer;

        const enJson = Convert.decodeUtf8(Convert.decryptAesCbc(ciphertextBuffer, keyBuffer, ivBuffer));
        const UrlJson = JSON.parse(enJson.replace(/(.*})(.*)/, '$1'));
        

        // 5. 构建图片数组
        const images = [];
        if (UrlJson?.chapter_images) {
            for (const imgPath of UrlJson.chapter_images) {
                images.push(`https://six.mhpic.net${imgPath}`);
            }
        }

        return { images };
},
         idMatch: null,
        // 启用标签翻译
        enableTagsTranslate: false,
    }
}
